home *** CD-ROM | disk | FTP | other *** search
/ Aminet 44 / Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso / Aminet / comm / mail / YAM23src.lha / Source / YAM_MAf.c < prev    next >
C/C++ Source or Header  |  2001-06-03  |  25KB  |  778 lines

  1. /***************************************************************************
  2.  
  3.  YAM - Yet Another Mailer
  4.  Copyright (C) 1995-2000 by Marcel Beck <mbeck@yam.ch>
  5.  Copyright (C) 2000-2001 by YAM Open Source Team
  6.  
  7.  This program is free software; you can redistribute it and/or modify
  8.  it under the terms of the GNU General Public License as published by
  9.  the Free Software Foundation; either version 2 of the License, or
  10.  (at your option) any later version.
  11.  
  12.  This program is distributed in the hope that it will be useful,
  13.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  GNU General Public License for more details.
  16.  
  17.  You should have received a copy of the GNU General Public License
  18.  along with this program; if not, write to the Free Software
  19.  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20.  
  21.  YAM Official Support Site :  http://www.yam.ch
  22.  YAM OpenSource project    :  http://sourceforge.net/projects/yamos/
  23.  
  24.  $Id: YAM_MAf.c,v 1.9.2.2 2001/06/03 22:42:02 laursen Exp $
  25.  
  26. ***************************************************************************/
  27.  
  28. #include "YAM.h"
  29. #include "YAM_rexx.h"
  30.  
  31. /* local protos */
  32. LOCAL void MA_ValidateStatus(struct Folder*);
  33. LOCAL char *MA_IndexFileName(struct Folder*);
  34. LOCAL BOOL MA_DetectUUE(FILE*);
  35. LOCAL void MA_GetRecipients(char*, struct Person**, int*);
  36.  
  37. /***************************************************************************
  38.  Module: Main - Folder handling
  39. ***************************************************************************/
  40.  
  41. /*** Index Maintenance ***/
  42.  
  43. /// MA_PromptFolderPassword
  44. //  Asks user for folder password
  45. BOOL MA_PromptFolderPassword(struct Folder *fo, APTR win)
  46. {
  47.    char passwd[SIZE_PASSWORD], prompt[SIZE_LARGE];
  48.    struct User *user = US_GetCurrentUser();
  49.  
  50.    if (fo->Flags&FOFL_FREEXS) return TRUE;
  51.    if (!Stricmp(fo->Password, user->Password)) return TRUE;
  52.    sprintf(prompt, GetStr(MSG_MA_GetFolderPass), fo->Name);
  53.    do {
  54.       *passwd = 0;
  55.       if (!StringRequest(passwd, SIZE_PASSWORD, GetStr(MSG_Folder), prompt, GetStr(MSG_Okay), NULL, GetStr(MSG_Cancel), TRUE, win)) return FALSE;
  56.    } while (Stricmp(passwd, fo->Password));
  57.    return TRUE;
  58. }
  59.  
  60. ///
  61. /// MA_ValidateStatus
  62. //  Avoids invalid status values
  63. LOCAL void MA_ValidateStatus(struct Folder *folder)
  64. {
  65.    struct Mail *mail;
  66.  
  67.    for (mail = folder->Messages; mail; mail = mail->Next)
  68.       if (mail->Status == STATUS_NEW)
  69.          if (folder->Type == FT_OUTGOING) MA_SetMailStatus(mail, STATUS_WFS);
  70.          else if (folder->Type == FT_SENT) MA_SetMailStatus(mail, STATUS_SNT);
  71.          else if (C->UpdateNewMail) MA_SetMailStatus(mail, STATUS_UNR);
  72. }
  73.  
  74. ///
  75. /// MA_IndexFileName
  76. //  Returns file name of folder index
  77. LOCAL char *MA_IndexFileName(struct Folder *folder)
  78. {
  79.    static char buffer[SIZE_PATHFILE];
  80.    strcpy(buffer, GetFolderDir(folder));
  81.    AddPart(buffer, ".index", SIZE_PATHFILE);
  82.    return buffer;
  83. }
  84.  
  85. ///
  86. /// MA_LoadIndex
  87. //  Loads a folder index from disk
  88. int MA_LoadIndex(struct Folder *folder, BOOL full)
  89. {
  90.    FILE *fh;
  91.    int indexloaded = 0;
  92.    char buf[SIZE_LARGE];
  93.  
  94. // KPrintF("Loading index for folder %s\n", folder->Name);
  95.    if (fh = fopen(MA_IndexFileName(folder), "r"))
  96.    {
  97.       struct FIndex fi;
  98.       BOOL corrupt = FALSE;
  99.  
  100.       Busy(GetStr(MSG_BusyLoadingIndex), folder->Name, 0, 0);
  101.       fread(&fi, sizeof(struct FIndex), 1, fh);
  102.       if (fi.ID == MAKE_ID('Y','I','N','3'))
  103.       {
  104.          folder->Total  = fi.Total;
  105.          folder->New    = fi.New;
  106.          folder->Unread = fi.Unread;
  107.          folder->Size   = fi.Size;
  108.          indexloaded++;
  109.  
  110.          if (full)
  111.          {
  112.             ClearMailList(folder, TRUE);
  113.             for (;;)
  114.             {
  115.                struct Mail mail;
  116.                struct ComprMail cmail;
  117.                clear(&mail, sizeof(struct Mail));               
  118.                if (fread(&cmail, sizeof(struct ComprMail), 1, fh) != 1) break;
  119.                if (cmail.MoreBytes > SIZE_LARGE)
  120.                {
  121. /*
  122. fpos_t pos;
  123. printf("WARNING: Index of folder '%s' CORRUPTED near mailfile '%s' (MoreBytes: 0x%x) - aborting!\n", folder->Name, cmail.MailFile, cmail.MoreBytes);
  124. if (!fgetpos(fh, &pos)) printf("File position: %ld\n", pos);
  125. */
  126.  
  127.                   corrupt = TRUE;
  128.                   break;
  129.                }
  130.  
  131.                fread(buf, 1, cmail.MoreBytes, fh);
  132.                strcpy(mail.Subject, GetNextLine(buf));
  133.                strcpy(mail.From.Address, GetNextLine(NULL));
  134.                strcpy(mail.From.RealName, GetNextLine(NULL));
  135.                strcpy(mail.To.Address, GetNextLine(NULL));
  136.                strcpy(mail.To.RealName, GetNextLine(NULL));
  137.                strcpy(mail.ReplyTo.Address, GetNextLine(NULL));
  138.                strcpy(mail.ReplyTo.RealName, GetNextLine(NULL));
  139.                mail.Folder = folder;
  140.                mail.Flags = (cmail.Flags&0x7ff);
  141.                strcpy(mail.MailFile, cmail.MailFile);
  142.                mail.Date = cmail.Date;
  143.                mail.Status = cmail.Status;
  144.                mail.Importance = cmail.Importance;
  145.                mail.cMsgID = cmail.cMsgID;
  146.                mail.cIRTMsgID = cmail.cIRTMsgID;
  147.                mail.Size = cmail.Size;
  148.                AddMailToList(&mail, folder);
  149.             }
  150.             indexloaded++;
  151.             folder->Flags &= ~FOFL_MODIFY;
  152.          }
  153.       }
  154.       BusyEnd;
  155.       fclose(fh);
  156.  
  157.       if (corrupt) {
  158.          MA_ScanMailBox(folder);
  159.          MA_SaveIndex(folder);
  160. //printf("Rescanned!\n");
  161.       }
  162.    }
  163.    return indexloaded;
  164. }
  165.  
  166. ///
  167. /// MA_SaveIndex
  168. //  Saves a folder index to disk
  169. BOOL MA_SaveIndex(struct Folder *folder)
  170. {
  171.    struct Mail *mail;
  172.    FILE *fh;
  173.    struct ComprMail cmail;
  174.    char buf[SIZE_LARGE];
  175.    struct FIndex fi;
  176.  
  177.    if (!(fh = fopen(MA_IndexFileName(folder), "w"))) return FALSE;
  178.    Busy(GetStr(MSG_BusySavingIndex), folder->Name, 0, 0);
  179.    fi.ID = MAKE_ID('Y','I','N','3');
  180.    fi.Total = folder->Total; fi.New = folder->New; fi.Unread = folder->Unread; fi.Size = folder->Size;
  181.    fwrite(&fi, sizeof(struct FIndex), 1, fh);
  182.    for (mail = folder->Messages; mail; mail = mail->Next)
  183.    {
  184.       clear(&cmail, sizeof(struct ComprMail));
  185.       sprintf(buf, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
  186.          mail->Subject,
  187.          mail->From.Address, mail->From.RealName,
  188.          mail->To.Address, mail->To.RealName,
  189.          mail->ReplyTo.Address, mail->ReplyTo.RealName);
  190.       cmail.Flags = mail->Flags;
  191.       strcpy(cmail.MailFile, mail->MailFile);
  192.       cmail.Date = mail->Date;
  193.       cmail.Status = mail->Status;
  194.       cmail.Importance = mail->Importance;
  195.       cmail.cMsgID = mail->cMsgID;
  196.       cmail.cIRTMsgID = mail->cIRTMsgID;
  197.       cmail.Size = mail->Size;
  198.       cmail.MoreBytes = strlen(buf);
  199.       fwrite(&cmail, sizeof(struct ComprMail), 1, fh);
  200.       fwrite(buf, 1, cmail.MoreBytes, fh);
  201.    }
  202.    fclose(fh);
  203.    folder->Flags &= ~FOFL_MODIFY;
  204.    BusyEnd;
  205.    return TRUE;
  206. }
  207.  
  208. ///
  209. /// MA_GetIndex
  210. //  Opens/unlocks a folder
  211. BOOL MA_GetIndex(struct Folder *folder)
  212. {
  213.    if (!folder) return FALSE;
  214.    if (folder->Type == FT_SEPARATOR) return FALSE;
  215.    if (folder->LoadedMode != 2)
  216.    {
  217.       if (*folder->Password && (folder->XPKType&1))
  218.          if (!MA_PromptFolderPassword(folder, G->MA->GUI.WI)) return FALSE;
  219.       if (!MA_LoadIndex(folder, TRUE))
  220.       {
  221.          MA_ScanMailBox(folder);
  222.          MA_SaveIndex(folder);
  223.       }
  224.       MA_ValidateStatus(folder);
  225.       folder->LoadedMode = 2;
  226.    }
  227.    return TRUE;
  228. }
  229.  
  230. ///
  231. /// MA_ExpireIndex
  232. //  Invalidates a folder index
  233. void MA_ExpireIndex(struct Folder *folder)
  234. {
  235.    if (!(folder->Flags&FOFL_MODIFY)) DeleteFile(MA_IndexFileName(folder));
  236.    folder->Flags |= FOFL_MODIFY;
  237. }
  238.  
  239. ///
  240. /// MA_UpdateIndexes
  241. //  Updates indices of all folders
  242. void MA_UpdateIndexes(BOOL initial)
  243. {
  244.    int i;
  245.    struct Folder **flist;
  246.  
  247.    if (flist = FO_CreateList())
  248.    {
  249.       for (i = 1; i <= (int)*flist; i++) if (flist[i]->Type != FT_SEPARATOR)
  250.          if (initial)
  251.          {
  252.             long dirdate = getft(GetFolderDir(flist[i]));
  253.             long inddate = getft(MA_IndexFileName(flist[i]));
  254.             if (dirdate > inddate+30 && inddate != -1)
  255.             {
  256.                DeleteFile(MA_IndexFileName(flist[i]));
  257.                MA_GetIndex(flist[i]);
  258.             }
  259.          }
  260.          else
  261.          {
  262.             if (flist[i]->LoadedMode == 2 && (flist[i]->Flags&FOFL_MODIFY)) MA_SaveIndex(flist[i]);
  263.          }
  264.       free(flist);
  265.    }
  266. }
  267.  
  268. ///
  269. /// MA_FlushIndexes
  270. //  Removes loaded folder indices from memory and closes folders
  271. void MA_FlushIndexes(BOOL all)
  272. {
  273.    int i;
  274.    struct Folder *fo, **flist, *actfo = FO_GetCurrentFolder();
  275.  
  276.    if (flist = FO_CreateList())
  277.    {
  278.       for (i = 1; i <= (int)*flist; i++)
  279.       {
  280.          fo = flist[i];
  281.          if ((fo->Type == FT_SENT || fo->Type == FT_CUSTOM || fo->Type == FT_CUSTOMSENT) && fo != actfo  && fo->LoadedMode == 2 && (all || (fo->Flags&FOFL_FREEXS)))
  282.          {
  283.             if (fo->Flags&FOFL_MODIFY) MA_SaveIndex(fo);
  284.             ClearMailList(fo, FALSE);
  285.             fo->LoadedMode = 1;
  286.             fo->Flags &= ~FOFL_FREEXS;
  287.          }
  288.       }
  289.       free(flist);
  290.       DoMethod(G->MA->GUI.LV_FOLDERS, MUIM_NList_Redraw, MUIV_NList_Redraw_All);
  291.    }
  292. }
  293.  
  294. void SAVEDS MA_FlushIndexFunc(void)
  295. {
  296.    MA_FlushIndexes(TRUE);
  297. }
  298. MakeHook(MA_FlushIndexHook, MA_FlushIndexFunc);
  299. ///
  300.  
  301. /*** Private functions ***/
  302. /// MA_ChangeFolder
  303. //  Changes to another folder
  304. void MA_ChangeFolder(struct Folder *folder)
  305. {
  306.    static struct Folder *lastfolder = NULL;
  307.    struct Folder *actfolder = FO_GetCurrentFolder();
  308.    BOOL folderopen = TRUE;
  309.    int i, pos = 0;
  310.  
  311.    if (actfolder != folder || actfolder != lastfolder)
  312.    {
  313.       struct MA_GUIData *gui = &G->MA->GUI;
  314.       set(gui->NL_MAILS, MUIA_ShortHelp, NULL);
  315.       if (lastfolder) lastfolder->LastActive = GetMUI(gui->NL_MAILS, MUIA_NList_Active);
  316.       if (folder) nnset(gui->NL_FOLDERS, MUIA_NList_Active, FO_GetFolderPosition(folder));
  317.       else folder = actfolder;
  318.       if (folder->Type == FT_SEPARATOR) folderopen = FALSE;
  319.       else if (!MA_GetIndex(folder)) folderopen = FALSE;
  320.       if (folderopen)
  321.       {
  322.          MA_SetSortFlag();
  323.          DisplayMailList(folder, gui->NL_MAILS);
  324.          DisplayStatistics(folder);
  325.  
  326.          if (C->JumpToNewMsg)
  327.          {
  328.             // jump to first or last unread mail in folder,
  329.             // depending on sort order
  330.  
  331.             int incr;
  332.  
  333.             if (folder->Sort[0] < 0 || folder->Sort[1] < 0)
  334.             {
  335.                get(gui->NL_MAILS, MUIA_NList_Entries, &i);
  336.                i--;
  337.                incr = -1;
  338.             }
  339.             else
  340.             {
  341.                i = 0;
  342.                incr = 1;
  343.             }
  344.  
  345.             while (1)
  346.             {
  347.                struct Mail *mail;
  348.                DoMethod(gui->NL_MAILS, MUIM_NList_GetEntry, i, &mail);
  349.                if (!mail) break;
  350.                if (mail->Status == STATUS_NEW || mail->Status == STATUS_UNR)
  351.                {
  352.                   pos = i;
  353.                   break;
  354.                }
  355.  
  356.                i += incr;
  357.             }
  358.          }
  359.  
  360.          set(gui->NL_MAILS, MUIA_NList_Active, pos);
  361.       }
  362.       set(gui->LV_MAILS, MUIA_Disabled, !folderopen);
  363.       lastfolder = folder;
  364.    }
  365. }
  366.  
  367. void SAVEDS MA_ChangeFolderFunc(void)
  368. {
  369.    struct Folder *folder = FO_GetCurrentFolder();
  370.    if (folder) MA_ChangeFolder(folder);
  371. }
  372. MakeHook(MA_ChangeFolderHook, MA_ChangeFolderFunc);
  373. ///
  374.  
  375. /*** Mail header scanning ***/
  376. /// MA_NewMailFile
  377. //  Returns an unique name for a new mail file
  378. char *MA_NewMailFile(struct Folder *folder, char *mailfile, int daynumber)
  379. {
  380.    static char buffer[SIZE_PATHFILE];
  381.    char mfile[SIZE_MFILE];
  382.    struct Mail *mail;
  383.    int cnt, mcnt = 0;
  384.    
  385.    if (!mailfile) mailfile = mfile;
  386.    if (!daynumber) { struct DateStamp ds; DateStamp(&ds); daynumber = ds.ds_Days; }
  387.    MA_GetIndex(folder);
  388.    for (mail = folder->Messages; mail; mail = mail->Next)
  389.       if (atoi(mail->MailFile) == daynumber)
  390.          if ((cnt = atoi(&(mail->MailFile)[6])) > mcnt) mcnt = cnt;
  391.    do {
  392.       sprintf(mailfile, "%05d.%03d", daynumber, ++mcnt);
  393.       strcpy(buffer, GetFolderDir(folder));
  394.       AddPart(buffer, mailfile, SIZE_PATHFILE);
  395.    } while (access(buffer,F_OK) == 0);
  396.    return buffer;
  397. }
  398.  
  399. ///
  400. /// MA_DetectUUE
  401. //  Checks if message contains an uuencoded file
  402. LOCAL BOOL MA_DetectUUE(FILE *fh)
  403. {
  404.    char *buffer;
  405.    BOOL found = FALSE;
  406.    int i;
  407.  
  408.    buffer = calloc(SIZE_LINE,1);
  409.    for (i = 0; GetLine(fh, buffer, SIZE_LINE) && !found && i < 30; i++)
  410.       if (!strncmp(buffer, "begin ", 6) && isdigit((int)buffer[6])) found = TRUE;
  411.    free(buffer);
  412.    return found;
  413. }
  414.  
  415. ///
  416. /// MA_ReadHeader
  417. //  Reads header lines of a message into memory
  418. struct Data2D Header = { 0, 0, NULL };
  419.  
  420. BOOL MA_ReadHeader(FILE *fh)
  421. {
  422.    char *buffer, *ptr, *head;
  423.    BOOL success = FALSE;
  424.    char prevcharset[SIZE_DEFAULT];
  425.  
  426.    buffer = calloc(SIZE_LINE,1);
  427.    head   = calloc(SIZE_LINE,1);
  428.    FreeData2D(&Header);
  429.    while (GetLine(fh, buffer, SIZE_LARGE))
  430.    {
  431.       if (!buffer[0]) { success = TRUE; break; }
  432.       clear(head, SIZE_LINE);
  433.       strcpy(prevcharset, "us-ascii");
  434.       RE_ProcessHeader(prevcharset, buffer, TRUE, head);
  435.       if ((buffer[0] == ' ' || buffer[0] == '\t') && Header.Used)
  436.       {
  437.          for (ptr = head; *ptr && ISpace(*ptr); ptr++);
  438.          ptr = StrBufCat(Header.Data[Header.Used-1], ptr);
  439.       }
  440.       else                      
  441.          ptr = StrBufCpy(AllocData2D(&Header, SIZE_DEFAULT), head);
  442.       Header.Data[Header.Used-1] = ptr;
  443.    }
  444.    free(buffer); free(head);
  445.    return success;
  446. }  
  447.  
  448. ///
  449. /// MA_FreeEMailStruct
  450. //  Frees an extended email structure
  451. void MA_FreeEMailStruct(struct ExtendedMail *email)
  452. {
  453.    if (email->SenderInfo) FreeStrBuf(email->SenderInfo);
  454.    if (email->Headers ) FreeStrBuf(email->Headers );
  455.    if (email->NoSTo)    free(email->STo);
  456.    if (email->NoCC )    free(email->CC );
  457.    if (email->NoBCC)    free(email->BCC);
  458.    clear(email, sizeof(struct ExtendedMail));
  459. }
  460.  
  461. ///
  462. /// MA_GetRecipients
  463. //  Extracts recipients from a header field
  464. LOCAL void MA_GetRecipients(char *h, struct Person **per, int *percnt)
  465. {
  466.    int cnt;
  467.    char *p = h, *next;
  468.    for (cnt = 0; *p;)
  469.    {
  470.       cnt++;
  471.       if (p = MyStrChr(p, ',')) p++; else break;
  472.    }
  473.    *percnt = cnt;
  474.    if (cnt)
  475.    {
  476.       *per = calloc(cnt, sizeof(struct Person));
  477.       for (cnt = 0, p = h; *p; cnt++)
  478.       {
  479.          if (next = MyStrChr(p, ',')) *next++ = 0;
  480.          ExtractAddress(p, (struct Person *)((ULONG)*per+cnt*sizeof(struct Person)));
  481.          if (!(p = next)) break;
  482.       }
  483.    }
  484. }
  485.  
  486. ///
  487. /// MA_ExamineMail
  488. //  Parses the header lines of a message and fills email structure
  489. struct ExtendedMail *MA_ExamineMail(struct Folder *folder, char *file, char *statstr, BOOL deep)
  490. {
  491.    static struct ExtendedMail email;
  492.    static struct Person pe;
  493.    struct Mail *mail = (struct Mail *)&email;
  494.    char *p, fullfile[SIZE_PATHFILE];
  495.    int ok, i, j;
  496.    struct DateStamp *foundDate = NULL;
  497.    FILE *fh;
  498.  
  499.    clear(&email, sizeof(struct ExtendedMail));
  500.    stccpy(mail->MailFile, file, SIZE_MFILE);
  501.    email.DelSend = !C->SaveSent;
  502.    if (fh = fopen(GetMailFile(fullfile, folder, mail), "r"))
  503.    {
  504.       BOOL xpk = FALSE;
  505.       if (fgetc(fh) == 'X') if (fgetc(fh) == 'P') if (fgetc(fh) == 'K') xpk = TRUE;
  506.       if (xpk)
  507.       {
  508.          fclose(fh);
  509.          if (!StartUnpack(GetMailFile(NULL, folder, mail), fullfile, folder)) return NULL;
  510.          fh = fopen(fullfile, "r");
  511.       }
  512.       else rewind(fh);
  513.    }
  514.    if (fh)
  515.    {
  516.       MA_ReadHeader(fh);
  517.       if (MA_DetectUUE(fh)) mail->Flags |= MFLAG_MULTIPART;
  518.       fclose(fh);
  519.       for (ok=i=0; i < Header.Used; i++)
  520.       {
  521.          char *value, *field = Header.Data[i];
  522.          if (value = strchr(field, ':'))
  523.          {
  524.             *value++ = 0;
  525.             if (!stricmp(field, "from"))
  526.             {
  527.                ok |= 1;
  528.                ExtractAddress(value, &pe);
  529.                mail->From =  pe;
  530.             }
  531.             if (!stricmp(field, "reply-to"))
  532.             {
  533.                ok |= 8;
  534.                ExtractAddress(value, &pe);
  535.                mail->ReplyTo = pe;
  536.             }
  537.             if (!stricmp(field, "original-recipient"))
  538.             {
  539.                ExtractAddress(value, &pe);
  540.                email.OriginalRcpt = pe;
  541.             }
  542.             if (!stricmp(field, "disposition-notification-to"))
  543.             {
  544.                ExtractAddress(value, &pe);
  545.                email.ReceiptTo = pe;
  546.                email.ReceiptType = RCPT_TYPE_ALL;
  547.                mail->Flags |= MFLAG_SENDMDN;
  548.             }
  549.             if (!stricmp(field, "return-view-to"))
  550.             {
  551.                ExtractAddress(value, &pe);
  552.                email.ReceiptTo = pe;
  553.                email.ReceiptType = RCPT_TYPE_READ;
  554.             }
  555.             if (!stricmp(field, "return-receipt-to"))
  556.             {
  557.                email.RetRcpt = TRUE;
  558.             }
  559.             if (!stricmp(field, "to") && !(ok & 2))
  560.             {
  561.                ok |= 2;
  562.                if (p = MyStrChr(value, ',')) *p++ = 0;
  563.                ExtractAddress(value, &pe);
  564.                mail->To = pe;
  565.                if (p)
  566.                {
  567.                   mail->Flags |= MFLAG_MULTIRCPT;
  568.                   if (deep && !email.NoSTo) MA_GetRecipients(p, &(email.STo), &(email.NoSTo));
  569.                }
  570.             }
  571.             if (!stricmp(field, "cc"))
  572.             {
  573.                mail->Flags |= MFLAG_MULTIRCPT;
  574.                if (deep && !email.NoCC) MA_GetRecipients(value, &(email.CC), &(email.NoCC));
  575.             }
  576.             if (!stricmp(field, "bcc"))
  577.             {
  578.                mail->Flags |= MFLAG_MULTIRCPT;
  579.                if (deep && !email.NoBCC) MA_GetRecipients(value, &(email.BCC), &(email.NoBCC));
  580.             }
  581.             if (!stricmp(field, "subject"))
  582.             {
  583.                ok |= 4;
  584.                stccpy(mail->Subject, Trim(value), SIZE_SUBJECT);
  585.             }
  586.             if (!stricmp(field, "message-id"))
  587.             {
  588.                mail->cMsgID = CompressMsgID(p = Trim(value));
  589.                stccpy(email.MsgID, p, SIZE_MSGID);
  590.             }
  591.             if (!stricmp(field, "in-reply-to"))
  592.             {
  593.                mail->cIRTMsgID = CompressMsgID(p = Trim(value));
  594.                stccpy(email.IRTMsgID, p, SIZE_MSGID);
  595.             }
  596.             if (!stricmp(field, "date"))
  597.             {
  598.                foundDate = ScanDate(value);
  599.             }
  600.             if (!stricmp(field, "importance"))
  601.             {
  602.                p = Trim(value);
  603.                if (!stricmp(p, "high")) mail->Importance = 1;
  604.                if (!stricmp(p, "low")) mail->Importance = -1;
  605.             }
  606.             if (!stricmp(field, "priority") && !mail->Importance)
  607.             {
  608.                p = Trim(value);
  609.                if (!stricmp(p, "urgent")) mail->Importance = 1;
  610.                if (!stricmp(p, "non-urgent")) mail->Importance = -1;
  611.             }
  612.             if (!stricmp(field, "content-type"))
  613.             {
  614.                p = Trim(value);
  615.                if (!strnicmp(p, "multipart/mixed", 15)) mail->Flags |= MFLAG_MULTIPART;
  616.                if (!strnicmp(p, "multipart/report", 16)) mail->Flags |= MFLAG_REPORT;
  617.                if (!strnicmp(p, "multipart/encrypted", 19)) mail->Flags |= MFLAG_CRYPT;
  618.                if (!strnicmp(p, "multipart/signed", 16)) mail->Flags |= MFLAG_SIGNED;
  619.             }
  620.             if (!stricmp(field, "x-senderinfo"))
  621.             {
  622.                mail->Flags |= MFLAG_SENDERINFO;
  623.                if (deep) email.SenderInfo = StrBufCpy(email.SenderInfo, value);
  624.             }
  625.             if (deep)
  626.             {
  627.                if (!stricmp(field, "x-yam-options"))
  628.                {
  629.                   if (strstr(value, "delsent")) email.DelSend = TRUE;
  630.                   if (p = strstr(value, "sigfile")) email.Signature = p[7]-'0'+1;
  631.                   for (j = SEC_SIGN; j <= SEC_SENDANON; j++) if (strstr(value, SecCodes[j])) email.Security = j;
  632.                }
  633.                if (!strnicmp(field, "x-yam-header-", 13))
  634.                {
  635.                   email.Headers = StrBufCat(StrBufCat(email.Headers, &field[13]), ":");
  636.                   email.Headers = StrBufCat(StrBufCat(email.Headers, value), "\\n");
  637.                }
  638.             }
  639.          }
  640.       }
  641.       FreeData2D(&Header);
  642.       if ((ok & 8) && !mail->ReplyTo.RealName[0] && !stricmp(mail->ReplyTo.Address, mail->From.Address)) strcpy(mail->ReplyTo.RealName, mail->From.RealName);
  643.       mail->Date.ds_Days   = foundDate ? foundDate->ds_Days   : atol(mail->MailFile);
  644.       mail->Date.ds_Minute = foundDate ? foundDate->ds_Minute : 0;
  645.       mail->Date.ds_Tick   = foundDate ? foundDate->ds_Tick   : 0;
  646.       mail->Size = FileSize(fullfile);
  647.       if (statstr)
  648.          for (mail->Status = STATUS_NEW, i = 0; i < STATUS_NEW; i++)
  649.             if (*statstr == *Status[i]) mail->Status = i;
  650.       FinishUnpack(fullfile);
  651.       return &email;
  652.    }
  653.    FinishUnpack(fullfile);
  654.    return NULL;
  655. }
  656.  
  657. ///
  658. /// MA_ScanMailBox
  659. //  Scans for message files in a folder directory
  660. void MA_ScanMailBox(struct Folder *folder)
  661. {
  662.    struct ExtendedMail *mail;
  663.    struct FileInfoBlock *fib;
  664.    BPTR lock;
  665.  
  666.    Busy(GetStr(MSG_BusyScanning), folder->Name, 0, 0);
  667.    ClearMailList(folder, TRUE);
  668.    fib = AllocDosObject(DOS_FIB,NULL);
  669.    if (lock = Lock(GetFolderDir(folder), ACCESS_READ))
  670.    {
  671.       Examine(lock, fib);
  672.       while (ExNext(lock,fib) && (IoErr() != ERROR_NO_MORE_ENTRIES))
  673.       {
  674.          DoMethod(G->App,MUIM_Application_InputBuffered);
  675.          if (IsValidMailFile(fib->fib_FileName))
  676.             if (fib->fib_Size)
  677.             {
  678.                if (mail = MA_ExamineMail(folder,fib->fib_FileName,fib->fib_Comment,FALSE))
  679.                {
  680.                   AddMailToList((struct Mail *)mail, folder);
  681.                   MA_FreeEMailStruct(mail);
  682.                }
  683.             }
  684.             else
  685.             {
  686.                char path[SIZE_PATHFILE];
  687.                NameFromLock(lock, path, SIZE_PATHFILE);
  688.                AddPart(path, fib->fib_FileName, SIZE_PATHFILE);
  689.                DeleteFile(path);
  690.             }
  691.       }
  692.       UnLock(lock);
  693.    }
  694.    FreeDosObject(DOS_FIB,fib);
  695.    BusyEnd;
  696. }
  697. ///
  698.  
  699. /*** Hooks ***/
  700. /// PO_InitFolderList
  701. //  Creates a popup list of all folders
  702. long SAVEDS ASM PO_InitFolderList(REG(a2,Object *pop))
  703. {  
  704.    int i;
  705.    struct Folder **flist;
  706.  
  707.    DoMethod(pop, MUIM_List_Clear);
  708.    DoMethod(pop, MUIM_List_InsertSingle, GetStr(MSG_MA_Cancel), MUIV_List_Insert_Bottom);
  709.    if (flist = FO_CreateList())
  710.    {
  711.       for (i = 1; i <= (int)*flist; i++) if (flist[i]->Type != FT_SEPARATOR)
  712.          DoMethod(pop, MUIM_List_InsertSingle, flist[i]->Name, MUIV_List_Insert_Bottom);
  713.       free(flist);
  714.    }
  715.    return TRUE;
  716. }
  717. MakeHook(PO_InitFolderListHook, PO_InitFolderList);
  718.  
  719. ///
  720. /// MA_LV_FDspFunc
  721. //  Folder listview display hook
  722. long SAVEDS ASM MA_LV_FDspFunc(REG(a2,char **array), REG(a1,struct Folder *entry))
  723. {
  724.    if (entry)
  725.    {
  726.       static char dispfold[SIZE_DEFAULT], disptot[SIZE_SMALL], dispunr[SIZE_SMALL], dispnew[SIZE_SMALL], dispsiz[SIZE_SMALL];
  727.       strcpy(array[0] = dispfold, entry->Name);
  728.       array[1] = array[2] = array[3] = array[4] = "";
  729.       *dispsiz = 0;
  730.       if (entry->Type == FT_SEPARATOR)
  731.          array[DISPLAY_ARRAY_MAX] = "\033E\033t\033c";
  732.       else
  733.       {
  734.          if (!*dispfold) sprintf(dispfold, "(%s)", FilePart(entry->Path));
  735.          if (entry->XPKType&1) strcat(dispfold, " \033o[0]");
  736.          if (entry->LoadedMode)
  737.          {
  738.             if (entry->New+entry->Unread) array[DISPLAY_ARRAY_MAX] = MUIX_PH;
  739.             sprintf(array[1] = disptot, "%d", entry->Total);
  740.             sprintf(array[2] = dispunr, "%d", entry->Unread);
  741.             sprintf(array[3] = dispnew, "%d", entry->New);
  742.             FormatSize(entry->Size, array[4] = dispsiz);
  743.          }
  744.       }
  745.    }
  746.    else 
  747.    {
  748.       array[0] = GetStr(MSG_Folder);
  749.       array[1] = GetStr(MSG_Total);
  750.       array[2] = GetStr(MSG_Unread);
  751.       array[3] = GetStr(MSG_New);
  752.       array[4] = GetStr(MSG_Size);
  753.    }
  754.    return 0;
  755. }
  756. MakeHook(MA_LV_FDspFuncHook,MA_LV_FDspFunc);
  757.  
  758. ///
  759. /// MA_MakeFOFormat
  760. //  Creates format definition for folder listview
  761. void MA_MakeFOFormat(APTR lv)
  762. {
  763.    int i;
  764.    int defwidth[FOCOLNUM] = { -1,-1,-1,-1,-1 };
  765.    char format[SIZE_LARGE];
  766.    BOOL first = TRUE;
  767.    *format = 0;
  768.    for (i = 0; i < FOCOLNUM; i++) if (C->FolderCols & (1<<i))
  769.    {
  770.       if (first) first = FALSE; else strcat(format, " BAR,");
  771.       sprintf(&format[strlen(format)], "COL=%ld W=%ld", i, defwidth[i]);
  772.       if (i) strcat(format, " P=\033r");
  773.    }
  774.    strcat(format, " BAR");
  775.    set(lv, MUIA_NList_Format, format);
  776. }
  777. ///
  778.